﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace OpenMediaOrganizer.MediaLibrary
{
    public class OMOLibrary
    {
        private List<MediaFolder> _MediaFolders;
        public List<MediaFolder> MediaFolders
        {
            get
            {
                if (_MediaFolders == null)
                {
                    _MediaFolders = new List<MediaFolder>();
                    _MediaFolders.Add(new MediaFolder()
                    {
                        Info = new DirectoryInfo(@"\\Enternainmentpc\m\Videos"),
                        Type = MediaFolderTypes.Misc
                    });
                    _MediaFolders.Add(new MediaFolder()
                    {
                        Info = new DirectoryInfo(@"\\Enternainmentpc\d\Videos\Family"),
                        Type = MediaFolderTypes.Movies
                    });
                    _MediaFolders.Add(new MediaFolder()
                    {
                        Info = new DirectoryInfo(@"\\Enternainmentpc\d\Videos\Grown Ups"),
                        Type = MediaFolderTypes.Movies
                    });
                    _MediaFolders.Add(new MediaFolder()
                    {
                        Info = new DirectoryInfo(@"\\Enternainmentpc\d\Videos\TV"),
                        Type = MediaFolderTypes.TV
                    });
                }
                return _MediaFolders;
            }
        }

        private List<TitleTemplate> _TitlePatterns;
        public List<TitleTemplate> TitlePatterns
        {
            get
            {
                if (_TitlePatterns == null)
                {
                    _TitlePatterns = new List<TitleTemplate>();
                    _TitlePatterns.Add(new TitleTemplate()
                    {
                        Patterns = new List<Regex>(new Regex[] 
                        { 
                            new Regex(@"(?<title>.*?(?=\d{4}))(?<date>\d{4}(?=.+))") 
                        }),
                        Name = "Title with date",
                        Elements = new List<string>(new string[] { "title", "date" }),
                        Template = "<<title>> (<<date>>)",
                        Priority = 100
                    });
                    _TitlePatterns.Add(new TitleTemplate()
                    {
                        Patterns = new List<Regex>(new Regex[]
                        { 
                            new Regex(@"(?<title>\d{4}.+(?=\(\d{4}\)))\((?<date>\d{4})\)")
                        }),
                        Name = "Date title with date",
                        Elements = new List<string>(new string[] { "title", "date" }),
                        Template = "<<title>> (<<date>>)",
                        Priority = 200
                    });
                    _TitlePatterns.Add(new TitleTemplate()
                    {
                        Patterns = new List<Regex>(new Regex[]
                        { 
                            new System.Text.RegularExpressions.Regex(@"(?<title>[a-zA-Z\s]+)")
                        }),
                        Name = "Title only",
                        Elements = new List<string>(new string[] { "title" }),
                        Template = "<<title>>",
                        Priority = 9999
                    });
                    _TitlePatterns.Add(new TitleTemplate()
                    {
                        Patterns = new List<Regex>(new Regex[]
                        { 
                            new System.Text.RegularExpressions.Regex(@"(?<series>^[\w\s]*?)(([Ss](?<season>\d{1,2})[Ee][Pp]?(?<episode>\d{1,2}))|([Ee][Pp]?(?<episode>\d{1,2}))|((?<season>\d{1,2})[Xx](?<episode>\d{1,2}))|((?<=Series)\s*?(?<episode>\d{1,2}))|([Ss]eason\s*?(?<season>\d{1,2})(?!\s*?[Ee]))|(([Ss]eason\s*?(?<season>\d{1,2}))\s*?([Ee]pisode\s*?(?<episode>\d{1,2})))|([Ee]pisode\s*?(?<episode>\d{1,2})))((?<name>[\w\s]*?)(?=(\r\n|$)))")
                        }),
                        Name = "TV Episode",
                        Elements = new List<string>(new string[] { "series", "season", "episode", "name" }),
                        Template = "<<series>> S<<season>>E<<episode>> <<name>>",
                        Priority = 10
                    });
                }
                _TitlePatterns.Sort(delegate(TitleTemplate t1, TitleTemplate t2)
                {
                    return t1.Priority.CompareTo(t2.Priority);
                });
                return _TitlePatterns;
            }
            set
            {
                _TitlePatterns = value;
            }
        }

        private List<string> _WhitespaceReplacements;
        public List<string> WhitespaceReplacements
        {
            get
            {
                if (_WhitespaceReplacements == null)
                {
                    _WhitespaceReplacements = new List<string>();
                    _WhitespaceReplacements.Add("[");
                    _WhitespaceReplacements.Add("]");
                    _WhitespaceReplacements.Add("{");
                    _WhitespaceReplacements.Add("}");
                    _WhitespaceReplacements.Add(".");
                    _WhitespaceReplacements.Add(",");
                    _WhitespaceReplacements.Add("/");
                    _WhitespaceReplacements.Add("-");
                    _WhitespaceReplacements.Add("_");
                    _WhitespaceReplacements.Add("<");
                    _WhitespaceReplacements.Add(">");
                    _WhitespaceReplacements.Add("^");
                    _WhitespaceReplacements.Add("$");
                    _WhitespaceReplacements.Add("#");
                    _WhitespaceReplacements.Add("@");
                    _WhitespaceReplacements.Add("|");
                    _WhitespaceReplacements.Add("~");
                    _WhitespaceReplacements.Add("'");
                    _WhitespaceReplacements.Add("(");
                    _WhitespaceReplacements.Add(")");
                }
                return _WhitespaceReplacements;
            }
            set
            {
                _WhitespaceReplacements = value;
            }
        }

        private List<string> _TextReplacements;
        public List<string> TextReplacements
        {
            get
            {
                if (_TextReplacements == null)
                {
                    _TextReplacements = new List<string>();
                    _TextReplacements.Add("klaxxon");
                    _TextReplacements.Add("dvdrip");
                    _TextReplacements.Add("xvid");
                    _TextReplacements.Add("maxspeed");
                    _TextReplacements.Add("divx");
                    _TextReplacements.Add("bugz");
                    _TextReplacements.Add("flawl3ss");
                    _TextReplacements.Add("720p");
                    _TextReplacements.Add("1080p");
                    _TextReplacements.Add("bluray");
                    _TextReplacements.Add("dts");
                    _TextReplacements.Add("x264");
                    _TextReplacements.Add("dxva");
                    _TextReplacements.Add("by winker");
                    _TextReplacements.Add("axxo");
                    _TextReplacements.Add("secretmyth");
                    _TextReplacements.Add("kingdom release");
                    _TextReplacements.Add("canus movies by jade");
                    _TextReplacements.Add("()");
                    _TextReplacements.Add("aac");
                    _TextReplacements.Add("h264");
                    _TextReplacements.Add("3li");
                    _TextReplacements.Add("brrip");
                    _TextReplacements.Add("bdrip");
                    _TextReplacements.Add(" eng ");
                    _TextReplacements.Add("fxg");
                    _TextReplacements.Add("1337x");
                    _TextReplacements.Add("r5");
                    _TextReplacements.Add("350mb each");
                    _TextReplacements.Add("hdtv");
                    _TextReplacements.Add(" rips ");
                    _TextReplacements.Add("jdmax");
                    _TextReplacements.Add("jaybob");
                    _TextReplacements.Add("nevstar");
                    _TextReplacements.Add("jns");
                    _TextReplacements.Add("avi");
                    _TextReplacements.Add("nwrg");
                    _TextReplacements.Add("crg");
                    _TextReplacements.Add("dbk");
                    _TextReplacements.Add("5 1 ch");
                    _TextReplacements.Add("avchd");
                    _TextReplacements.Add("subs");
                    _TextReplacements.Add("3hrs");
                    _TextReplacements.Add("mp4");
                    _TextReplacements.Add("ripminion");
                    _TextReplacements.Add("mrtower");
                    _TextReplacements.Add("dvsky");
                    _TextReplacements.Add("nedivx");
                    _TextReplacements.Add("vomit");
                    _TextReplacements.Add("resourcerg");
                    _TextReplacements.Add("kidzcorner");
                    _TextReplacements.Add("bugzbunny");
                    _TextReplacements.Add("j t r");
                    _TextReplacements.Add("fqm");
                    _TextReplacements.Add("gayteam");
                    _TextReplacements.Add("by trindade");
                    _TextReplacements.Add("www");
                    _TextReplacements.Add("ibizatorrent");
                    _TextReplacements.Add(" com ");
                    _TextReplacements.Add("matroska");
                    _TextReplacements.Add("nhanc3");
                    _TextReplacements.Add("occor");
                    _TextReplacements.Add("6ch");
                    _TextReplacements.Add("720x436");
                    _TextReplacements.Add("rhood");
                    _TextReplacements.Add("10vol");
                    _TextReplacements.Add("by winker");
                    _TextReplacements.Add("besthd");
                    _TextReplacements.Add("braveheart2112");
                    _TextReplacements.Add("h33t");
                    _TextReplacements.Add("xvid diamond");
                    _TextReplacements.Add("xvid immortals");
                    _TextReplacements.Add("usabit");
                    _TextReplacements.Add("sirius share");
                    _TextReplacements.Add("bmt");
                    _TextReplacements.Add("divx511");
                    _TextReplacements.Add("tvrip");
                    _TextReplacements.Add("mvgroup");
                    _TextReplacements.Add(" org ");
                    _TextReplacements.Add("mvgforum");
                    _TextReplacements.Add("greenbud1969");
                    _TextReplacements.Add("jocktheripper");
                    _TextReplacements.Add("covers subs");
                    _TextReplacements.Add("sinners");
                    _TextReplacements.Add("tlf");
                    _TextReplacements.Add("kids release");
                    _TextReplacements.Add("reidy");
                    _TextReplacements.Add("extrascene rg");
                    _TextReplacements.Add("extrascene");
                    _TextReplacements.Add("multi autio");
                    _TextReplacements.Add("crazy torrent");
                    _TextReplacements.Add("2lions team");
                    _TextReplacements.Add("xvid reward");
                    _TextReplacements.Add("cycopenquin");
                    _TextReplacements.Add("gkline");
                    _TextReplacements.Add(" ika ");
                    _TextReplacements.Add("limited dvdrip");
                    _TextReplacements.Add("xvid bulldozer");
                    _TextReplacements.Add("xvid arrow");
                    _TextReplacements.Add("tfx");
                    _TextReplacements.Add("norar");
                    _TextReplacements.Add("xvid amiable");
                    _TextReplacements.Add("xvid dimension");
                    _TextReplacements.Add("hd");
                    _TextReplacements.Add("720p oar");
                    _TextReplacements.Add(" lse ");
                    _TextReplacements.Add("xvid larceny");
                    _TextReplacements.Add("xvid diverse");
                    _TextReplacements.Add("dd2 0");
                    _TextReplacements.Add("spd");
                    _TextReplacements.Add("dvd5");
                    _TextReplacements.Add("dd5 1");
                    _TextReplacements.Add("clt");
                    _TextReplacements.Add("720p dual");
                    _TextReplacements.Add("fxm");
                    _TextReplacements.Add(" lol ");
                    _TextReplacements.Add(" notv ");
                    _TextReplacements.Add("sharereactor");
                    _TextReplacements.Add("sfm");
                    _TextReplacements.Add("f9255acc");
                    _TextReplacements.Add("0e102ea9");
                }
                return _TextReplacements;
            }
            set
            {
                _TextReplacements = value;
            }
        }

        private List<FileInfo> _Files;
        public List<FileInfo> Files
        {
            get
            {
                if (_Files == null)
                {
                    _Files = new List<FileInfo>();
                }
                return _Files;
            }
            set
            {
                _Files = value;
            }
        }

        private List<DirectoryInfo> _Directories;
        public List<DirectoryInfo> Directories
        {
            get
            {
                if (_Directories == null)
                {
                    _Directories = new List<DirectoryInfo>();
                }
                return _Directories;
            }
            set
            {
                _Directories = value;
            }
        }

        public string GetNewName(DirectoryInfo dir)
        {
            return GetNewName(dir.Parent, dir.Name);
        }
        public string GetNewName(FileInfo dir)
        {
            try
            {
                return GetNewName(dir.Directory, dir.Name);
            }
            catch (Exception ex)
            {
                return dir.Name;
            }
        }
        public string GetNewName(DirectoryInfo parentDir, string oldName)
        {
            foreach (string whitespaceCharacter in WhitespaceReplacements)
            {
                oldName = oldName.Replace(whitespaceCharacter, " ");
            }

            foreach (string replacement in TextReplacements)
            {
                System.Text.RegularExpressions.Regex removalRegex = new System.Text.RegularExpressions.Regex(String.Format(@"(?<pre>.*?)(?<found>(?i){0})(?<post>.*)", replacement));
                System.Text.RegularExpressions.Match match = removalRegex.Match(oldName);
                if (match != null && match.Groups["found"] != null && match.Groups["found"].Value != "")
                    oldName = match.Groups["pre"].Value + match.Groups["post"].Value;
            }

            foreach (TitleTemplate tt in TitlePatterns)
            {
                if (tt.Patterns[0].Matches(oldName).Count > 0)
                {
                    System.Text.RegularExpressions.Match match = tt.Patterns[0].Matches(oldName)[0];
                    string newName = tt.Template;
                    Regex templateGroup = new Regex(@"(?<=\<\<)\w+?(?=\>\>)");
                    foreach (Match groupMatch in templateGroup.Matches(tt.Template))
                    {
                        newName = newName.Replace(String.Format("<<{0}>>", groupMatch.Groups[0].Value), match.Groups[groupMatch.Groups[0].Value] == null ? "" : match.Groups[groupMatch.Groups[0].Value].Value);
                    }
                    oldName = newName;
                    break;
                }
            }

            return oldName.Replace("    ", " ").Replace("   ", " ").Replace("  ", " ").Trim();
        }

        public bool IsMediaFolder(DirectoryInfo dir)
        {
            bool result = false;
            result = MediaFolders.Find(folder => folder.Info.FullName == dir.FullName) != null;
            return result;
        }

        public void RefreshDirectories()
        {
            foreach (MediaFolder folder in MediaFolders)
            {
                RefreshDirectory(folder.Info);
            }
        }

        public void RefreshDirectory(DirectoryInfo dir)
        {
            Directories.Add(dir);
            RefreshFiles(dir);
            foreach (DirectoryInfo subDir in dir.GetDirectories())
            {
                RefreshDirectory(subDir);
            }
        }

        public void RefreshFiles(DirectoryInfo dir)
        {
            foreach (FileInfo file in dir.GetFiles())
            {
                string removalsFileName = Path.GetFileNameWithoutExtension(file.Name) + " ";
                string removalsExtension = Path.GetExtension(file.Name);
                switch (removalsExtension.ToUpper())
                {
                    case ".AVI":
                    case ".DIVX":
                    case ".MPG":
                    case ".MPEG":
                    case ".MP4":
                    case ".M4A":
                    case ".3GP":
                    case ".WMV":
                    case ".DVX":
                    case ".MKV":
                    case ".SRT":
                    case ".SUB":
                    case ".TXT":
                    case ".XVID":
                        Files.Add(file);
                        break;
                    default:
                        break;
                }
            }
        }
    }
}
